package top.yehot.cmmu.spring.handler;

import java.util.List;
import java.util.stream.Collectors;

import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import lombok.extern.slf4j.Slf4j;
import top.yehot.cmmu.core.base.JBaseException;
import top.yehot.cmmu.core.base.JResult;
import top.yehot.cmmu.core.enums.BaseResCodeEnum;
import top.yehot.cmmu.core.model.vo.LabelValueVO;

/**
 * 全局异常
 * 
 * @author lquan
 * @date 2022年4月2日 下午4:34:41
 */
@Slf4j
@RestController
@ControllerAdvice
public class GlobalExceptionHandler {

	// 参数信息异常
	@ExceptionHandler(value = MethodArgumentTypeMismatchException.class)
    public JResult<?> methodArgumentTypeMismatchExc(MethodArgumentTypeMismatchException e) {
        log.error(BaseResCodeEnum.PARAM_ERROR.getMessage(), e);
        return JResult.of(BaseResCodeEnum.PARAM_ERROR);
    }
	
	// 参数校验信息异常
	@ExceptionHandler(value = MethodArgumentNotValidException.class)
    public JResult<?> methodArgumentNotValidExc(MethodArgumentNotValidException e) {
		log.error(BaseResCodeEnum.PARAM_NOT_VALID.getMessage(), e);
		List<LabelValueVO> errList = e.getBindingResult().getAllErrors().stream().map(err -> {
			if (err instanceof FieldError) {
				FieldError fieldErr = (FieldError) err;
				return LabelValueVO.of(fieldErr.getField(), fieldErr.getDefaultMessage());
			}
			return LabelValueVO.of(err.getObjectName(), err.getDefaultMessage());
		}).collect(Collectors.toList());
		return JResult.of(BaseResCodeEnum.PARAM_NOT_VALID, errList);
    }
	
	// 自定义异常
	@ExceptionHandler(value = JBaseException.class)
    public JResult<?> baseExc(JBaseException e) {
        log.error(e.getMessage(), e);
        return JResult.of(e.getStatus(), e.getMessage());
    }

    // Assert 断言抛出的异常
	@ExceptionHandler(value = IllegalArgumentException.class)
    public JResult<?> illegaExc(IllegalArgumentException e) {
        log.error(e.getMessage(), e);
        return JResult.of(BaseResCodeEnum.OTHER_ERROR);
    }

	// 兜底异常
	@ExceptionHandler(value = Throwable.class)
    public JResult<?> exc(Throwable e) {
        log.error(BaseResCodeEnum.OTHER_ERROR.getMessage(), e);
        return JResult.of(BaseResCodeEnum.OTHER_ERROR);
    }
}
